// Filename : cgiHandler.cpp
// Implemention of class cgiHandler

#include "cgihandler.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>

using namespace std;

// Parsh information from HTTP server 
// and store them into dictonarys
void 
CgiHandler::handlerInit() {
	loadEnvironmentVar();
	
	string requestMethod = getEnvValue( "REQUEST_METHOD" );

	if( requestMethod.empty() ) {
		return;
	}

	string queryString;
	int contentLength = 0;
	if ( 0 == strcasecmp( "GET", requestMethod.c_str() ) ) {
		queryString = getEnvValue( "QUERY_STRING" );
		contentLength = queryString.size();
		//cout << __LINE__ << " " << queryString << endl;
	}
	else if ( 0 == strcasecmp ( "POST", requestMethod.c_str() ) ) {
		
		if ( isNumber( getEnvValue( "CONTENT_LENGTH" ) ) ) {
			
			contentLength = atoi( getEnvValue( "CONTENT_LENGTH" ).c_str() );
			
			bool testResult = doBeforeReadData( contentLength );

			if ( testResult == false ) {
				contentLength = 0;
			}
			else {
				char * tmp = NULL;

				if (( tmp = (char *)malloc( contentLength+1 )) == NULL ) {
					contentLength = 0;
				}
				else {
					cin.get( tmp, contentLength+1 );
					queryString = string( tmp );
				}

				if(!tmp) {
					free(tmp);	
				}
				//cout << __LINE__ << " " << queryString << endl;
			}
		}
	} 
	else {
		return;
	}


	if( contentLength != 0 ) {
		//cout << __LINE__ << " " << contentLength << endl;
		loadQueryVar(queryString);
	}
}

string 
CgiHandler::getEnvValue( string EnvVarName ) const {
	return environmentVar[EnvVarName]; 
}

string
CgiHandler::getQueryValue( string QueryVarName ) const {
	return queryVar[ QueryVarName ];
}

bool
CgiHandler::doBeforeReadData( int length ) {
	if ( length > MAX_LENGTH ) {
		return false;
	}

	return true;
}

void
CgiHandler::loadEnvironmentVar() {	
	for( int i = 0; i < NUM_OF_ENV_VARS; i++ ) {
		string tmp = getEnvWithCheck( ENV_VARS[ i ] );
		if( tmp.empty() ) {
			continue;
		}
		else {
			environmentVar[ ENV_VARS [ i ] ] = tmp;
		}
	}
}


// parser;split;store queryString
void 
CgiHandler::loadQueryVar( string queryString ) {
	string tmp;
	for ( int i = 0, j = 0; i < queryString.size(); i++, j++ ) {
		if ( queryString[i] == '+' ) {
			tmp.append( 1, ' ' );
		}
		else if ( queryString[i] == '%' ) {
			tmp.append( 1, H2D( queryString[ i + 1 ] ) * 16 +
					 	   	H2D( queryString[ i + 2 ] ) );
			i += 2;
		}
		else {
			tmp.append( 1, queryString[i] );
		}
	}

	//cout << __LINE__ << " " << tmp << endl;
	
	string key;
	string value;
	string * point = &key;
	for ( int i = 0; i < tmp.size(); i++ ) {
			
		if( tmp[i] == '=' ) {
			point = &value;
		} 
		else if ( tmp[i] == '&' ) {

			if( !key.empty() ) {
				if ( !queryVar[key].empty() ) {
					queryVar[key] = queryVar[key] + " " + value;
				}
				else {
					queryVar[key] = value;
				}
				//queryVar[key] = value;
				//cout << key << "->" << value << endl;
			}

			key.erase( 0, key.size() );
			value.erase( 0, value.size() );
			point = &key;
		}
		else {
			point->append( 1, tmp[i] );
		}
	}

	// store the last variabal
	if ( !key.empty() ) {
		queryVar[key] = value;
	}
}

bool
CgiHandler::isNumber( string testString ) const {
	for ( int i = 0; i < testString.size(); i++ ) {
		if ( testString[i] > '9' || testString[i] < '0' ) {
			return false;
		}
	}

	return true;
}

string 
CgiHandler::getEnvWithCheck( string EnvVarName ) const {
	char * tmp = getenv( EnvVarName.c_str() );
	if ( tmp == NULL ) {
		return string("");
	}
	else {
		return string(tmp);
	}
}

// End of cgihandler.cpp
